package com.rongxun.common.base.mvvm.viewmodel;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import com.rongxun.api.config.ResponseCode;
import com.rongxun.api.exception.ApiException;
import com.rongxun.api.exception.EmptyDataException;
import com.rongxun.api.utils.FlyLog;
import com.rongxun.common.R;
import com.rongxun.common.aroute.RouteUtil;
import com.rongxun.common.base.mvvm.event.UIChangeLiveData;
import com.rongxun.common.base.mvvm.model.BaseModel;
import com.rongxun.common.manager.ActivityManager;
import com.yanzhenjie.permission.AndPermission;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.net.UnknownServiceException;
import java.util.HashMap;
import java.util.Map;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.subscribers.ResourceSubscriber;
import retrofit2.HttpException;

/**
 * 创建者     forza
 * 创建时间   2019/11/29 18:09
 * 描述
 */
public abstract class BaseViewModel<M extends BaseModel> extends AndroidViewModel implements IBaseViewModel, Consumer<Disposable> {
    private M                   mModel;
    private UIChangeLiveData    mUIChangeLiveData;
    private CompositeDisposable mCompositeDisposable;

    public BaseViewModel(@NonNull Application application, M model) {
        super(application);
        this.mModel = model;
    }

    @Override
    public void onAny(LifecycleOwner owner, Lifecycle.Event event) {

    }

    private Intent mIntent;

    public Intent getIntent() {

        return mIntent;
    }

    public void setIntent(Intent intent) {
        mIntent = intent;
    }

    protected M getModel() {
        return mModel;
    }


    public UIChangeLiveData getUIChangeLiveData() {
        if (mUIChangeLiveData == null) {
            mUIChangeLiveData = new UIChangeLiveData();
        }
        return mUIChangeLiveData;
    }

    @Override
    public void accept(Disposable disposable) {
        if (mCompositeDisposable == null) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);
    }


    protected void addSubscribe(Disposable disposable) {
        if (mCompositeDisposable == null) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);
    }


    @SuppressLint("WrongConstant")
    protected void checkPermissions(final String... permissions) {
        AndPermission.with(ActivityManager.getInstance().currentActivity()).runtime().permission(permissions)
                .onGranted(data -> getPermissionsSuccessful(permissions))
                .onDenied(data -> showPermissionsError(getApplication().getApplicationContext().getString(R.string.no_permission)))
                .start();
    }

    protected void getPermissionsSuccessful(String[] permissions) {

    }

    ;


    protected void showPermissionsError(String string) {


    }


    @Override
    protected void onCleared() {
        super.onCleared();
        if (mModel != null) {
            mModel.onCleared();
        }

        if (mCompositeDisposable != null) {
            mCompositeDisposable.dispose();
        }
        mIntent = null;
    }

    public abstract class BaseSubscriber<T> extends ResourceSubscriber<T> {

        @Override
        protected void onStart() {
            super.onStart();
            postShowInitLoadViewEvent(true);
        }

        @Override
        public void onNext(T t) {
            if (t == null) {
                postShowNoDataViewEvent(true);
            } else {
                postShowNoDataViewEvent(false);
                onSuccess(t);
            }
        }

        protected abstract void onSuccess(T t);

        @Override
        public void onError(Throwable t) {

            int errorCode = ResponseCode.FAILURE;
            getApplication().getString(R.string.httpexception);
            String errorMsg = getApplication().getString(R.string.unknownexception);

            if (t instanceof HttpException) {

                HttpException httpException = (HttpException) t;
                errorCode = httpException.code();
                errorMsg = httpException.message();

            } else if (t instanceof SocketTimeoutException) {  //VPN open

                errorMsg = getApplication().getString(R.string.sockettimeoutexception);

            } else if (t instanceof ConnectException) {

                errorMsg = getApplication().getString(R.string.connectexception);

            } else if (t instanceof RuntimeException) {

                errorMsg = getApplication().getString(R.string.unknownexception);

            } else if (t instanceof UnknownHostException) {

                errorMsg = getApplication().getString(R.string.unknownhostexception);

            } else if (t instanceof UnknownServiceException) {

                errorMsg = getApplication().getString(R.string.unknownserviceexception);

            } else if (t instanceof IOException) {  //飞行模式等

                errorMsg = getApplication().getString(R.string.ioexception);

            } else if (t instanceof ApiException) {

                ApiException httpException = (ApiException) t;
                errorCode = httpException.getErrorCode();
                errorMsg = httpException.getMessage();


            } else if (t instanceof EmptyDataException) {

                errorMsg = "数据为空";
            }
            FlyLog.e("errorCode" + errorCode + "errorMsg" + errorMsg);

            onFailure(errorCode, errorMsg);


        }

        private void onFailure(int code, String message) {

            postShowInitLoadViewEvent(false);
            postShowNetWorkErrViewEvent(true);
            switch (code) {
                case ResponseCode.TOKEN_INVALID:
                    RouteUtil.forwardLogin();
                    break;

            }
            Toast.makeText(getApplication().getApplicationContext(), message, Toast.LENGTH_SHORT).show();
            disposeEorCode(message, code);


        }

        protected abstract void disposeEorCode(String message, int code);

        @Override
        public void onComplete() {
            postShowInitLoadViewEvent(false);
        }
    }

    public interface ParameterField {
        String CLASS          = "CLASS";
        String CANONICAL_NAME = "CANONICAL_NAME";
        String BUNDLE         = "BUNDLE";
    }

    public void postShowInitLoadViewEvent(boolean show) {
        if (mUIChangeLiveData != null) {
            mUIChangeLiveData.getShowInitLoadViewEvent().postValue(show);
        }
    }

    public void postShowTransLoadingViewEvent(boolean show) {
        if (mUIChangeLiveData != null) {
            mUIChangeLiveData.getShowTransLoadingViewEvent().postValue(show);
        }
    }

    public void postShowNoDataViewEvent(boolean show) {
        if (mUIChangeLiveData != null) {
            mUIChangeLiveData.getShowNoDataViewEvent().postValue(show);
        }
    }

    public void postShowNetWorkErrViewEvent(boolean show) {
        if (mUIChangeLiveData != null) {
            mUIChangeLiveData.getShowNetWorkErrViewEvent().postValue(show);
        }
    }

    public void postStartActivityEvent(Class<?> clz, Bundle bundle) {
        Map<String, Object> params = new HashMap<>();
        params.put(ParameterField.CLASS, clz);
        if (bundle != null) {
            params.put(ParameterField.BUNDLE, bundle);
        }
        mUIChangeLiveData.getStartActivityEvent().postValue(params);
    }


    public void postFinishActivityEvent() {
        mUIChangeLiveData.getFinishActivityEvent().call();
    }


    @Override
    public void onCreate() {

    }

    @Override
    public void onDestroy() {
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onStop() {

    }

    @Override
    public void onResume() {

    }

    @Override
    public void onPause() {

    }
}
